#ifndef WXSPROPERTYGRIDMANAGER_H
#define WXSPROPERTYGRIDMANAGER_H

#include <wx/scrolwin.h>
#include <wx/toolbar.h>
#include <wx/stattext.h>
#include <wx/button.h>
#include <wx/hashset.h>
#include <wx/dcclient.h>
#include <wx/propgrid/propgrid.h>
#include <wx/propgrid/manager.h>
#include <prep.h>

class wxsPropertyContainer;
class wxsProperty;


class wxsPropertyGridManager: public wxPropertyGridManager {
    DECLARE_CLASS( wxsPropertyGridManager )
  public:
    wxsPropertyGridManager(
      wxWindow* parent,
      wxWindowID id = -1,
      const wxPoint& pos = wxDefaultPosition,
      const wxSize& size = wxDefaultSize,
      long style = wxPGMAN_DEFAULT_STYLE | wxPG_SPLITTER_AUTO_CENTER,
      const wxChar* name = wxPropertyGridManagerNameStr );
    virtual ~wxsPropertyGridManager();
    static inline wxsPropertyGridManager* Get() { return Singleton; }
    inline wxsPropertyContainer* GetContainer() { return MainContainer; }
  protected:
    virtual void OnContainerChanged( M_Code_unused wxsPropertyContainer* NewContainer ) {}
  private:
    void UnbindAll();
    void UnbindPropertyContainer( wxsPropertyContainer* PC, bool doFreeze = true );


    void Update( wxsPropertyContainer* PC );

    // prevent warning for overloaded virtual that is hiding the method in the base class.
    using wxPropertyGridManager::Update;
    long Register( wxsPropertyContainer* Container, wxsProperty* Property, wxPGId Id, long Index );
    void NewPropertyContainerStart();
    void NewPropertyContainerAddProperty( wxsProperty* Property, wxsPropertyContainer* Container );
    void NewPropertyContainerFinish( wxsPropertyContainer* Container );
    void DeleteTemporaryPropertiesList();
    void SetNewMainContainer( wxsPropertyContainer* NewMain );
    void OnChange( wxPropertyGridEvent& event );
    void OnDoubleClick( wxPropertyGridEvent& event );
    struct SelectionData {
      int m_PageIndex;
      wxString m_PropertyName;
    };
    void StoreSelected( SelectionData* Data = 0 );
    void RestoreSelected( const SelectionData* Data = 0 );
    static wxsPropertyGridManager* Singleton;
    struct TemporaryPropertiesList {
      wxsProperty* Property;
      wxsPropertyContainer* Container;
      int Priority;
      TemporaryPropertiesList* Next;
    };

    WX_DEFINE_ARRAY( wxPGId, wxArrayPGId );
    WX_DEFINE_ARRAY( wxsProperty*, wxArrayProps );
    WX_DEFINE_ARRAY( wxsPropertyContainer*, wxArrayCont );

    WX_DECLARE_HASH_SET( wxsPropertyContainer*, wxPointerHash, wxPointerEqual, wxSetCont );

    wxArrayPGId  PGIDs;                         ///< \brief Array of property identifiers
    wxArrayProps PGEntries;                     ///< \brief Array mapping entries in grid to properties
    wxArrayLong  PGIndexes;                     ///< \brief Array of internal property indexes used inside wxsProperty
    wxArrayCont  PGContainers;                  ///< \brief Array of container objects associated with properties
    wxSetCont    PGContainersSet;               ///< \brief Set of used containers, will be used to quickly determine if given container is used in manager
    wxsProperty* PreviousProperty;              ///< \brief Previous property used in Register()
    long         PreviousIndex;
    wxsPropertyContainer* MainContainer;
    TemporaryPropertiesList* PropertiesList;
    SelectionData LastSelection;
    DECLARE_EVENT_TABLE()

    friend class wxsProperty;
    friend class wxsPropertyContainer;
};


#define wxsPGRID() wxsPropertyGridManager::Get()

#endif
